﻿using System.Data.SqlClient;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Modules._2DoTasks.Components.ExceptionHandling;
using DotNetNuke.Modules._2DoTasks.Components.Interfaces;
using DotNetNuke.Modules._2DoTasks.Data;

namespace DotNetNuke.Modules._2DoTasks.Components.Controllers
{
    /// <summary>
    /// Controller object with business logic for Projects
    /// </summary>
    public class ProjectController : IRepository<Entities._Project, int>
    {
        private UnitOfWork _uof;

        #region IRepository<_Project>

        public ProjectController(UnitOfWork uof)
        {
            _uof = uof;
        }

        /// <summary>
        /// Gets the Project with the passed id
        /// </summary>
        /// <param name="ProjectId">the Project id</param>
        /// <param name="additionalFields">not used in Project entity</param>
        /// <returns>returns a Project object</returns>
        public Entities._Project Get(int ProjectId, params object[] additionalFields)
        {
            return CBO.FillObject<Entities._Project>(DataProvider.Instance().GetProject(ProjectId, this._uof.PortalId, _uof.CurrentUser.UserID));
        }

        /// <summary>
        /// Gets the Project with the passed name
        /// </summary>
        /// <param name="ProjectName">the Project name</param>
        /// <param name="additionalFields">not used in Project entity</param>
        /// <returns>returns a Project object</returns>
        public Entities._Project Get(string ProjectName)
        {
            return CBO.FillObject<Entities._Project>(DataProvider.Instance().GetProject(ProjectName, this._uof.PortalId, _uof.CurrentUser.UserID));
        }

        /// <summary>
        /// Gets the Project where the name starts with the passed parameter
        /// </summary>
        /// <param name="ProjectName">the Project name</param>
        /// <param name="additionalFields">not used in Project entity</param>
        /// <returns>returns a list of Project objects</returns>
        public System.Collections.Generic.List<Entities._Project> GetStartsWith(string ProjectName)
        {
            return CBO.FillCollection<Entities._Project>(DataProvider.Instance().GetProjectStartsWith(ProjectName, this._uof.PortalId, _uof.CurrentUser.UserID));
        }

        /// <summary>
        /// Returns all Projects
        /// </summary>
        /// <returns>retuns list of Projects</returns>
        public System.Collections.Generic.List<Entities._Project> GetAll()
        {
            return CBO.FillCollection<Entities._Project>(DataProvider.Instance().GetAllProjects(this._uof.PortalId, _uof.CurrentUser.UserID));
        }

        /// <summary>
        /// Returns all archived Projects
        /// </summary>
        /// <returns>retuns list of Projects</returns>
        public System.Collections.Generic.List<Entities._Project> GetArchived()
        {
            return CBO.FillCollection<Entities._Project>(DataProvider.Instance().GetArchived(this._uof.PortalId, _uof.CurrentUser.UserID));
        }

        /// <summary>
        /// Adds a new entity
        /// </summary>
        /// <param name="entity">entity to create</param>
        public void Add(Entities._Project entity)
        {
            try
            {
                entity.CreatedByUserID = this._uof.CurrentUser.UserID;
                entity.ModuleID = this._uof.ModuleId;
                entity.PortalId = this._uof.PortalId;

                entity.ProjectId = DataProvider.Instance().Add(entity);
            }
            catch (SqlException exc)
            {
                if (exc.Message.Contains("un_Prj_Name"))
                    throw new ProjectValidationException("Project name must be unique.",
                        SharedEnum.CrudState.Update,
                        (int)InsertStatus.DUPLICATENAME);

                throw exc;
            }
        }

        /// <summary>
        /// Updates a Project
        /// </summary>
        /// <param name="entity">Project to update</param>
        public void Update(Entities._Project entity)
        {
            try
            {
                entity.LastModifiedUserID = this._uof.CurrentUser.UserID;
                entity.ModuleID = this._uof.ModuleId;
                entity.PortalId = this._uof.PortalId;

                DataProvider.Instance().Update(entity);
            }
            catch (SqlException exc)
            {
                if (exc.Message.Contains("NOTMANAGER"))
                    throw new ProjectValidationException("The user has insuficient permissions for updating the project.",
                        SharedEnum.CrudState.Update,
                        (int)UpdateStatus.NOTMANAGER);

                if (exc.Message.Contains("un_Prj_Name"))
                    throw new ProjectValidationException("Project name must be unique.",
                        SharedEnum.CrudState.Update,
                        (int)UpdateStatus.DUPLICATENAME);

                throw exc;
            }
        }

        /// <summary>
        /// Deletes an existing Project
        /// </summary>
        /// <param name="entity">Project to delete</param>
        public void Delete(Entities._Project entity)
        {
            try
            {
                entity.ModuleID = this._uof.ModuleId;
                entity.PortalId = this._uof.PortalId;
                DataProvider.Instance().Delete(entity, this._uof.CurrentUser.UserID);
            }
            catch (SqlException exc)
            {
                if (exc.Message.Contains("NOTMANAGER"))
                    throw new ProjectValidationException("The user has insuficient permissions for deleting the project.",
                        SharedEnum.CrudState.Delete,
                        (int)DeleteStatus.NOTMANAGER);

                if (exc.Message.Contains("PROJECTWITHTASKS"))
                    throw new ProjectValidationException("Project cannot be delete while there's tasks.",
                        SharedEnum.CrudState.Delete,
                        (int)DeleteStatus.PROJECTWITHTASKS);

                throw exc;
            }
        }

        #endregion IRepository<_Project>

        #region "Crud Enums"

        public enum InsertStatus
        {
            DUPLICATENAME = -1
        }

        public enum UpdateStatus
        {
            DUPLICATENAME = -1,
            NOTMANAGER = -2
        }

        public enum DeleteStatus
        {
            NOTMANAGER = -1,
            PROJECTWITHTASKS = -2
        }

        #endregion "Crud Enums"
    }
}